﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace MaterialDemo.Utility
{
    public class ObjectMapping
    {
        /// <summary>
        /// 将一个对象，自动映射成另一个属性相同的对象
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static TResult BasedExpression<TSource, TResult>(TSource source)
        {
            ParameterExpression param = Expression.Parameter(typeof(TSource), "s"); //定义参数，这个s可以自己随便命名
            List<MemberBinding> memberBindingList = new List<MemberBinding>();//创建属性映射集合

            var properties = typeof(TResult).GetProperties();//目标对象的所有属性

            foreach (PropertyInfo item in properties)//循环构建属性表达式映射“对”
            {


                MemberExpression p_source = Expression.Property(param, typeof(TSource).GetProperty(item.Name));//得到的结果：s.CourseId,
                MemberBinding memberBinding = Expression.Bind(item, p_source);  //的I到的结果CourseId = s.CourseId,
                memberBindingList.Add(memberBinding);//把两个属性的牵手后的内容保存到结合中


            }
            MemberInitExpression body = Expression.MemberInit(Expression.New(typeof(TResult)), memberBindingList.ToArray());
            //调试body我们发现已经形成下面的代码
            //new NewCourse()
            //{
            //    CourseId = s.CourseId,
            //    CourseName = s.CourseName,
            //    UnitPrice = s.UnitPrice,
            //    CourseLevel = s.CourseLevel
            //}
            //最后，我们通过Lambda方法，生成表达式目录树,目的是为了后面能够编译成委托，供我们调用
            Expression<Func<TSource, TResult>> resultLambda =
                Expression.Lambda<Func<TSource, TResult>>(
                    body, new ParameterExpression[] { param });

            //将表达式目录树编译成委托，因为我们调用的时候，必须是一个方法！
            return resultLambda.Compile()(source);
        }




        /// <summary>
        /// 对比两个类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="newT"></param>
        /// <param name="oldT"></param>
        /// <returns></returns>
        public static string CompareType<T>(T newT, T oldT)
        {

            StringBuilder sb = new StringBuilder();

            Type typeNew = newT.GetType();
            Type typeOld = oldT.GetType();
            //1.获取所有公共属性(Public)
            PropertyInfo[] pisNew = typeNew.GetProperties();
            PropertyInfo[] pisOld = typeOld.GetProperties();

            //遍历两个T类型，遍历属性，并作比较
            for (int i = 0; i < pisNew.Length; i++)
            {
                //获取属性名
                string newName = pisNew[i].Name;
                string oldName = pisOld[i].Name;

                //如果的更新时间和更新人ID，添加时间和添加人ID跳过
                if (newName == "Update_ID" || newName == "Update_Time" || newName == "Add_ID" || newName == "Add_Time")
                {
                    continue;
                }

                //获取属性的值
                object newValue = pisNew[i].GetValue(newT, null);
                object oldValue = pisOld[i].GetValue(oldT, null);

                //获取属性对应的自定义特性别名              
                string descriptionName = "";
                if (pisNew[i].IsDefined(typeof(DescriptionAttribute), true))
                {
                    DescriptionAttribute attribute = (DescriptionAttribute)pisNew[i].GetCustomAttribute(typeof(DescriptionAttribute));
                    descriptionName = attribute.Description;
                }
                else
                {
                    descriptionName = newName.ToString();
                }

                //引用类型的比较，使用Equals要注意null的情况
                if (newValue == null && oldValue == null)
                {
                    continue;
                }
                if (newValue == null && oldValue != null)
                {
                    sb.Append("修改了" + descriptionName + "：\"" + oldValue + "\"改成了\"" + newValue + "\"；");
                    continue;
                }
                if (newValue != null && oldValue == null)
                {
                    sb.Append("修改了" + descriptionName + "：\"" + oldValue + "\"改成了\"" + newValue + "\"；");
                    continue;
                }
                if (!newValue.Equals(oldValue))
                {
                    sb.Append("修改了" + descriptionName + "：\"" + oldValue + "\"改成了\"" + newValue + "\"；");
                }

            }
            if (sb.Length == 0)
            {
                sb.Append("和原数据一致");
            }
            return sb.ToString();

        }
    }
}
